package com.uinnova.product.eam.service.impl;

import cn.hutool.core.date.DateUtil;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.uinnova.product.eam.base.exception.ServerException;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.diagram.DiagramReviewInfo;
import com.uinnova.product.eam.comm.diagram.DiagramReviewState;
import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.feign.workable.entity.FLOWSTATUS;
import com.uinnova.product.eam.feign.workable.entity.HistoryTaskResponse;
import com.uinnova.product.eam.feign.workable.entity.PorcessResponse;
import com.uinnova.product.eam.feign.workable.entity.TaskResponse;
import com.uinnova.product.eam.model.EamArtifactVo;
import com.uinnova.product.eam.model.constants.FlowableConstant;
import com.uinnova.product.eam.model.es.ChangeAssigneeRecord;
import com.uinnova.product.eam.model.es.CommunicateRecord;
import com.uinnova.product.eam.service.ChangeAssigneeRecordService;
import com.uinnova.product.eam.service.CommunicateRecordService;
import com.uinnova.product.eam.service.IEamArtifactSvc;
import com.uinnova.product.eam.service.es.DiagramReviewInfoDao;
import com.uinnova.product.eam.service.flowable.FlowableApprovalSvc;
import com.uinnova.product.eam.service.fx.GeneralPushSvc;
import com.uinnova.product.eam.vo.DiagramApproveInfo;
import com.uinnova.product.eam.vo.GTApproveRecord;
import com.uinnova.product.eam.vo.GTApproveRecordTask;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.service.eam.ESDiagramSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.permission.base.SysOrg;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.business.UserInfo;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.util.ESUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Component(value = FlowableConstant.GT_DIAGRAM_APPROVE)
public class GTDiagramApprovalSvcImpl implements FlowableApprovalSvc {

    @Resource
    private FlowableFeign flowableFeign;
    @Resource
    private GeneralPushSvc generalPushSvc;
    @Resource
    private ESDiagramSvc esDiagramSvc;
    @Resource
    private IUserApiSvc userApiSvc;
    @Resource
    private IEamArtifactSvc artifactSvc;
    @Autowired
    private ChangeAssigneeRecordService changeAssigneeRecordService;
    @Autowired
    private DiagramReviewInfoDao diagramReviewInfoDao;
    @Resource
    private CommunicateRecordService communicateRecordService;

    @Override
    public List<String> getApprovalUser(String businessKey, String taskKey) {
        return null;
    }

    @Override
    public List<String> countersignChildUser(String businessKey, String taskKey) {
        return null;
    }

    @Override
    public void reject(String businessKey) {
        Map<String, Object> routerVariables = getApprovalRouterVariables(businessKey);
        Long diagramId = Long.valueOf(routerVariables.get("diagramId").toString());
        // 处理视图状态
        esDiagramSvc.updateFlowStatusByIds(Collections.singletonList(diagramId), 1);
    }

    @Override
    public void childReject(String childBusinessKey) {

    }

    @Override
    public void pass(String businessKey) {
        Map<String, Object> routerVariables = getApprovalRouterVariables(businessKey);
        Long dirId = Long.valueOf(routerVariables.get("releaseDirId").toString());
        String releaseDesc = BinaryUtils.isEmpty(routerVariables.get("releaseDesc")) ? "" : routerVariables.get("releaseDesc").toString();
        TermQueryBuilder query = QueryBuilders.termQuery("diagramEnergy.keyword", businessKey);
        List<DiagramReviewInfo> listByQuery = diagramReviewInfoDao.getListByQuery(query);
        if (CollectionUtils.isEmpty(listByQuery)) {
            throw new IllegalArgumentException("未找到视图评审记录");
        }
        // 一个视图一个审批记录
        DiagramReviewInfo diagramReviewInfo = listByQuery.get(0);
        diagramReviewInfo.setState(DiagramReviewState.PASS);
        diagramReviewInfo.setProcessFinishTime(ESUtil.getNumberDateTime());
        diagramReviewInfoDao.saveOrUpdate(diagramReviewInfo);
        // 发布视图 发布视图中有处理视图状态的逻辑
        log.info("############# 工作流开启视图发布，发布参数：diagramId【{}】，dirDesc【{}】，dirId【{}】", businessKey, releaseDesc, dirId);
        generalPushSvc.publishDiagram(businessKey, releaseDesc, dirId, null, Boolean.FALSE, true);
        log.info("############# 工作流完成视图发布");
    }

    @Override
    public void cancel(String businessKey) {
        Map<String, Object> routerVariables = getApprovalRouterVariables(businessKey);
        Long diagramId = Long.valueOf(routerVariables.get("diagramId").toString());
        TermQueryBuilder query = QueryBuilders.termQuery("diagramEnergy.keyword", businessKey);
        List<DiagramReviewInfo> listByQuery = diagramReviewInfoDao.getListByQuery(query);
        if (CollectionUtils.isEmpty(listByQuery)) {
            throw new IllegalArgumentException("未找到视图评审记录");
        }
        DiagramReviewInfo diagramReviewInfo = listByQuery.get(0);
        diagramReviewInfo.setState(DiagramReviewState.TERM);
        diagramReviewInfo.setProcessFinishTime(ESUtil.getNumberDateTime());
        diagramReviewInfoDao.saveOrUpdate(diagramReviewInfo);
        // 处理视图状态
        esDiagramSvc.updateFlowStatusByIds(Collections.singletonList(diagramId), 0);
    }

    /**
     * 根据业务定义key (视图ID) 获取当前流程中的全局变量
     *
     * @param businessKey 业务定义key (视图ID)
     * @return 流程全局变量
     */
    public Map<String, Object> getApprovalRouterVariables(String businessKey) {
        // 获取审批流程信息 todo 这里的 processDefinitionKey 先写死
        PorcessResponse processInstance = flowableFeign.getProcessInstanceByBusinessIdAndProcessDefinitionKey(businessKey, FlowableConstant.GT_DIAGRAM_APPROVE);
        if (BinaryUtils.isEmpty(processInstance)) {
            throw new ServerException("流程异常");
        }
        return processInstance.getRouterVariables();
    }

    public DiagramApproveInfo approveInfo(String processInstanceId, String businessKey, String taskId) {
        if (StringUtils.isBlank(processInstanceId) || StringUtils.isBlank(businessKey)) {
            throw new BinaryException("缺少参数");
        }
        List<ESDiagram> diagramList = esDiagramSvc.queryDBDiagramInfoByIds(new String[]{businessKey});
        if (CollectionUtils.isEmpty(diagramList)) {
            throw new BinaryException("未找到当前视图");
        }
        TaskResponse taskInfo = null;
        if (StringUtils.isNotBlank(taskId)) {
            taskInfo = flowableFeign.getTaskInfoByTaskId(taskId);
            if (taskInfo == null) {
                throw new BinaryException("未找到当前任务");
            }
        }

        ESDiagram diagram = diagramList.get(0);
        PorcessResponse porcessResponse = flowableFeign.getProcessInstanceByProcessInstanceId(processInstanceId);
        if (porcessResponse == null || StringUtils.isBlank(porcessResponse.getProcessInstanceId())) {
            throw new BinaryException("未找到当前流程");
        }
        DiagramApproveInfo approveInfo = new DiagramApproveInfo();
        if (taskInfo != null) {
            approveInfo.setTaskEnd(taskInfo.getTaskEndTime() != null);
        }
        approveInfo.setProcessEnd(!FLOWSTATUS.ACTIVE.equals(porcessResponse.getStatus()));
        approveInfo.setDiagramName(diagram.getName());
        approveInfo.setDEnergy(diagram.getDEnergy());
        approveInfo.setModifyTime(transDateFormat(diagram.getModifyTime(), "yyyy/MM/dd HH:mm:ss"));
        approveInfo.setSubmitTime(transDateFormat(ESUtil.getNumberDateTime(porcessResponse.getStartTime()), "yyyy/MM/dd HH:mm:ss"));
        approveInfo.setReleaseDesc("-");
        Map<String, Object> routerVariables = porcessResponse.getRouterVariables();
        if (!BinaryUtils.isEmpty(routerVariables)
                && routerVariables.containsKey("releaseDesc")
                && routerVariables.get("releaseDesc") != null
                && StringUtils.isNotBlank(routerVariables.get("releaseDesc").toString())) {
            approveInfo.setReleaseDesc(routerVariables.get("releaseDesc").toString());
        }
        Set<String> userLoginCodes = new HashSet<>();
        if (StringUtils.isNotBlank(diagram.getOwnerCode())) {
            userLoginCodes.add(diagram.getOwnerCode());
        }
        if (StringUtils.isNotBlank(porcessResponse.getProcessStartUserId())) {
            userLoginCodes.add(porcessResponse.getProcessStartUserId());
        }
        Map<String, UserInfo> userInfoMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(userLoginCodes)) {
            CSysUser cdt = new CSysUser();
            cdt.setLoginCodes(userLoginCodes.toArray(new String[userLoginCodes.size()]));
            List<UserInfo> userInfos = userApiSvc.getUserInfoByCdt(cdt, true);
            if (!CollectionUtils.isEmpty(userInfos)) {
                userInfoMap = userInfos.stream().collect(Collectors.toMap(UserInfo::getLoginCode, Function.identity(), (k1, k2) -> k1));
            }
        }
        approveInfo.setCreatorName("-");
        if (StringUtils.isNotBlank(diagram.getOwnerCode()) && userInfoMap.containsKey(diagram.getOwnerCode())) {
            UserInfo creator = userInfoMap.get(diagram.getOwnerCode());
            approveInfo.setCreatorName(creator.getUserName());
            approveInfo.setCreator(creator.getLoginCode());
            approveInfo.setCreatorIcon(creator.getIcon());
            String creatorOrgName = "-";
            if (!CollectionUtils.isEmpty(creator.getOrgs())) {
                List<SysOrg> orgs = new ArrayList<>(creator.getOrgs());
                orgs.sort(Comparator.comparing(SysOrg::getId));
                creatorOrgName = orgs.iterator().next().getOrgName();
            }
            approveInfo.setCreatorOrgName(creatorOrgName);
        }
        approveInfo.setSubmitterName("-");
        if (StringUtils.isNotBlank(porcessResponse.getProcessStartUserId())
                && userInfoMap.containsKey(porcessResponse.getProcessStartUserId())) {
            UserInfo submitter = userInfoMap.get(porcessResponse.getProcessStartUserId());
            approveInfo.setSubmitterName(submitter.getUserName());
            approveInfo.setSubmitter(submitter.getLoginCode());
            approveInfo.setSubmitterIcon(submitter.getIcon());
            String submitterOrgName = "-";
            if (!CollectionUtils.isEmpty(submitter.getOrgs())) {
                List<SysOrg> orgs = new ArrayList<>(submitter.getOrgs());
                orgs.sort(Comparator.comparing(SysOrg::getId));
                submitterOrgName = orgs.iterator().next().getOrgName();
            }
            approveInfo.setSubmitterOrgName(submitterOrgName);
        }
        Long artifactId = BinaryUtils.isEmpty(diagram.getViewType()) ? 0L : Long.parseLong(diagram.getViewType());
        approveInfo.setArtifactName("-");
        if (artifactId != 0L) {
            EamArtifactVo artifactVo = artifactSvc.queryArtifact(artifactId);
            if (artifactVo != null && StringUtils.isNotBlank(artifactVo.getArtifactName())) {
                approveInfo.setArtifactName(artifactVo.getArtifactName());
                approveInfo.setArtifactId(artifactId);
            }
        }
        return approveInfo;
    }

    private String transDateFormat(Long date, String format) {
        if (date == null) {
            return "-";
        }
        SimpleDateFormat timeFormatter = new SimpleDateFormat("yyyyMMddHHmmss");
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.format(timeFormatter.parse(date.toString()));
        } catch (ParseException e) {
            throw new BinaryException(e);
        }
    }

    public GTApproveRecord approveRecords(String processInstanceId) {
        GTApproveRecord approveRecord = new GTApproveRecord();
        List<HistoryTaskResponse> historyTasks = new ArrayList<>();
        List<HistoryTaskResponse> histories = flowableFeign.getHistoryTaskByCurrentProcessInstanceId(processInstanceId);
        List<TaskResponse> actives = flowableFeign.getCurrentTaskByCurrentProcessInstanceId(processInstanceId);
        List<GTApproveRecordTask> newTasks = new ArrayList<>();
        List<HistoryTaskResponse> oldTasks = new ArrayList<>();
        // 处理历史任务 提交-驳回-撤回等
        if (!BinaryUtils.isEmpty(histories)) {
            histories = histories.stream()
                    .filter(h -> !h.getVariables().get("pass").equals("autoCLose"))
                    .sorted(Comparator.comparing(HistoryTaskResponse::getCommitTime))
                    .collect(Collectors.toList());
            extracted(histories);
            historyTasks.addAll(histories);
        }
        // 新类型 历史数据
        List<GTApproveRecordTask> newHistoryTask = createNewTask(historyTasks);
        //当前任务
        List<HistoryTaskResponse> currentTasks = new ArrayList<>();
        // 处理当前任务并转换为历史任务响应
        Set<String> assignees = new HashSet<>();
        if (!CollectionUtils.isEmpty(actives)) {
            Set<String> currentAssigneeLoginCodes = actives.stream()
                    .map(TaskResponse::getUserId)
                    .collect(Collectors.toSet());
            CSysUser cSysUser = new CSysUser();
            cSysUser.setLoginCodes(currentAssigneeLoginCodes.toArray(new String[0]));
            List<SysUser> sysUsers = userApiSvc.getSysUserByCdt(cSysUser);
            Map<String, SysUser> userMap = sysUsers.stream()
                    .collect(Collectors.toMap(SysUser::getLoginCode, u -> u));

            for (TaskResponse active : actives) {
                HistoryTaskResponse response = new HistoryTaskResponse();
                response.setTaskId(active.getTaskId());
                response.setTaskName(active.getTaskName());
                response.setUserId(active.getUserId());
                response.setCommitTime(active.getTaskCreateTime());
                response.setProcessInstanceName(active.getProcessInstanceName());

                Map<String, Object> vars = new ConcurrentHashMap<>();
                vars.put("pass", "todo");
                SysUser user = userMap.get(active.getUserId());
                vars.put("user", user != null ? user.getUserName() : active.getUserId());
                vars.put("icon", user != null ? user.getIcon() : "");
                response.setVariables(vars);

                assignees.add(user != null ? user.getUserName() : active.getUserId());
                currentTasks.add(response);
            }
            approveRecord.setCurrentAssignees(String.join(",", assignees));
        }
        // 新类型 当前数据
        List<GTApproveRecordTask> newCurrentTasks = new ArrayList<>();
        if (!CollectionUtils.isEmpty(currentTasks)) {
             newCurrentTasks = createNewTask(currentTasks);
        }

        // 处理转办记录
        // 历史任务和当前任务合并，转办填充和沟通用
        List<HistoryTaskResponse> hisAndCurrentTasks = new ArrayList<>();
        hisAndCurrentTasks.addAll(historyTasks);
        hisAndCurrentTasks.addAll(currentTasks);
        List<HistoryTaskResponse> changeTasks = new ArrayList<>();
        // 新类型 转办数据
        List<GTApproveRecordTask> newChangeTasks = new ArrayList<>();
        getChangeAssignee(changeTasks,newChangeTasks,processInstanceId,hisAndCurrentTasks);
        // 处理沟通记录
        List<HistoryTaskResponse> communicateTasks = new ArrayList<>();
        // 新类型 转办数据
        List<GTApproveRecordTask> newCommunicateTasks = new ArrayList<>();
        getCommunicate(communicateTasks, newCommunicateTasks, processInstanceId, hisAndCurrentTasks);

        //组装数据
        oldTasks.addAll(historyTasks);
        oldTasks.addAll(currentTasks);
        oldTasks.addAll(changeTasks);
        oldTasks.addAll(communicateTasks);
        newHistoryTask.addAll(newChangeTasks);
        newHistoryTask.addAll(newCommunicateTasks);
        //根据 commitTime 字段进行排序，从小到大
        newHistoryTask.sort(Comparator.comparing(GTApproveRecordTask::getCommitTime));
        newTasks.addAll(newHistoryTask);
        if (!CollectionUtils.isEmpty(newCurrentTasks)) {
            newTasks.addAll(newCurrentTasks);
        }
        approveRecord.setTasks(oldTasks);
        approveRecord.setNewTasks(newTasks);
        return approveRecord;
    }

    private void getCommunicate(List<HistoryTaskResponse> communicateTasks, List<GTApproveRecordTask> newCommunicateTasks, String processInstanceId, List<HistoryTaskResponse> hisAndCurrentTasks) {
        List<CommunicateRecord> communicateRecords = communicateRecordService.queryByProcessInstanceId(processInstanceId)
                .stream().sorted(Comparator.comparing(CommunicateRecord::getCommunicateTime)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(communicateRecords)) {
            // 获取相关用户信息
            Set<String> involvedUsers = communicateRecords.stream().flatMap(r ->
                    Stream.of(r.getCommunicateUser(), r.getCommunicatePromoter())).collect(Collectors.toSet());
            CSysUser userQuery = new CSysUser();
            userQuery.setLoginCodes(involvedUsers.toArray(new String[0]));
            Map<String, SysUser> userMap = userApiSvc.getSysUserByCdt(userQuery).stream()
                    .collect(Collectors.toMap(SysUser::getLoginCode, u -> u));

            // 按任务分组处理转办记录
            Map<String, List<CommunicateRecord>> taskCommunicateMap = communicateRecords.stream()
                    .collect(Collectors.groupingBy(CommunicateRecord::getTaskId));

            for (HistoryTaskResponse task : hisAndCurrentTasks) {
                List<CommunicateRecord> communicateRecordList = taskCommunicateMap.getOrDefault(task.getTaskId(), Collections.emptyList());
                for (CommunicateRecord communicateRecord : communicateRecordList) {
                    HistoryTaskResponse changeResponse = createCommunicateResponse(communicateRecord, userMap, task);
                    communicateTasks.add(changeResponse);
                    newCommunicateTasks.add(createChangeAssigneeTask(changeResponse));
                }
            }
        }
    }

    private HistoryTaskResponse createCommunicateResponse(CommunicateRecord record,
                                                             Map<String, SysUser> userMap,
                                                             HistoryTaskResponse originalTask) {
        HistoryTaskResponse response = new HistoryTaskResponse();
        response.setTaskId(originalTask.getTaskId());
        response.setTaskName(originalTask.getTaskName());
        response.setUserId(record.getCommunicateUser());
        response.setCommitTime(parseOperateTime(record.getCommunicateTime()));
        response.setProcessInstanceName(originalTask.getProcessInstanceName());

        Map<String, Object> vars = new ConcurrentHashMap<>();
        // 是否是沟通回复
        if (record.isReback()) {
            vars.put("pass", "communicate-bak");

        }else{
            vars.put("pass", "communicate");
        }
        SysUser fromUser = userMap.get(record.getCommunicatePromoter());
        SysUser toUser = userMap.get(record.getCommunicateUser());
        vars.put("user", fromUser != null ? fromUser.getUserName() : record.getCommunicatePromoter());
        vars.put("icon", fromUser != null ? fromUser.getIcon() : "");
        vars.put("toUser", toUser != null ? toUser.getUserName() : record.getCommunicateUser());
        vars.put("remarks", StringUtils.defaultString(record.getRemarks(), ""));
        response.setVariables(vars);
        return response;
    }

    private HistoryTaskResponse createChangeAssigneeResponse(ChangeAssigneeRecord record,
                                                             Map<String, SysUser> userMap,
                                                             HistoryTaskResponse originalTask) {
        HistoryTaskResponse response = new HistoryTaskResponse();
        response.setTaskId(originalTask.getTaskId());
        response.setTaskName(originalTask.getTaskName());
        response.setUserId(record.getOrignAssignee());
        response.setCommitTime(parseOperateTime(record.getOperateTime()));
        response.setProcessInstanceName(originalTask.getProcessInstanceName());

        Map<String, Object> vars = new ConcurrentHashMap<>();
        vars.put("pass", "change");
        SysUser fromUser = userMap.get(record.getOrignAssignee());
        SysUser toUser = userMap.get(record.getNowAssignee());
        vars.put("user", fromUser != null ? fromUser.getUserName() : record.getOrignAssignee());
        vars.put("icon", fromUser != null ? fromUser.getIcon() : "");
        vars.put("toUser", toUser != null ? toUser.getUserName() : record.getNowAssignee());
        vars.put("remarks", StringUtils.defaultString(record.getRemarks(), ""));
        response.setVariables(vars);

        return response;
    }

    private GTApproveRecordTask createChangeAssigneeTask(HistoryTaskResponse response) {
        GTApproveRecordTask task = new GTApproveRecordTask();
        task.setTaskIds(Collections.singletonList(response.getTaskId()));
        task.setTaskName(response.getTaskName());
        task.setCommitTime(response.getCommitTime());
        task.setUserIds(Collections.singletonList(response.getUserId()));
        task.setProcessInstanceName(response.getProcessInstanceName());
        task.setVariables(response.getVariables());
        task.setDescription(response.getDescription());
        task.setAssignees(Collections.singletonList(
                new GTApproveRecordTask.Assignee(
                        response.getVariables().get("user").toString(),
                        response.getTaskId()
                )
        ));
        return task;
    }

    private void getChangeAssignee(List<HistoryTaskResponse> changeTasks, List<GTApproveRecordTask> newChangeTasks,
                                   String processInstanceId, List<HistoryTaskResponse> hisAndCurrentTasks) {
        List<ChangeAssigneeRecord> changeRecords = changeAssigneeRecordService.queryByProcessInstanceId(processInstanceId)
                .stream().sorted(Comparator.comparing(ChangeAssigneeRecord::getOperateTime)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(changeRecords)) {
            // 获取相关用户信息
            Set<String> involvedUsers = changeRecords.stream().flatMap(r ->
                    Stream.of(r.getOrignAssignee(), r.getNowAssignee())).collect(Collectors.toSet());
            CSysUser userQuery = new CSysUser();
            userQuery.setLoginCodes(involvedUsers.toArray(new String[0]));
            Map<String, SysUser> userMap = userApiSvc.getSysUserByCdt(userQuery).stream()
                    .collect(Collectors.toMap(SysUser::getLoginCode, u -> u));

            // 按任务分组处理转办记录
            Map<String, List<ChangeAssigneeRecord>> taskChangeMap = changeRecords.stream()
                    .collect(Collectors.groupingBy(ChangeAssigneeRecord::getTaskId));

            for (HistoryTaskResponse task : hisAndCurrentTasks) {
                List<ChangeAssigneeRecord> changes = taskChangeMap.getOrDefault(task.getTaskId(), Collections.emptyList());
                for (ChangeAssigneeRecord change : changes) {
                    HistoryTaskResponse changeResponse = createChangeAssigneeResponse(change, userMap, task);
                    changeTasks.add(changeResponse);
                    newChangeTasks.add(createChangeAssigneeTask(changeResponse));
                }
            }
        }
    }

    private Date parseOperateTime(Long timeStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        LocalDateTime dateTime = LocalDateTime.parse(String.valueOf(timeStr), formatter);
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }


    private List<GTApproveRecordTask> createNewTask(List<HistoryTaskResponse> tasks) {
        String stage = String.valueOf(tasks.get(0).getVariables().get("pass"));
        List<List<HistoryTaskResponse>> groupStage = new ArrayList<>();
        List<HistoryTaskResponse> s = new ArrayList<>();
        for (HistoryTaskResponse task : tasks) {
            if (!stage.equals(String.valueOf(task.getVariables().get("pass")))) {
                groupStage.add(EamUtil.copy(s, HistoryTaskResponse.class));
                stage = String.valueOf(task.getVariables().get("pass"));
                s = new ArrayList<>();
            }
            s.add(task);
        }
        groupStage.add(EamUtil.copy(s, HistoryTaskResponse.class));

        List<GTApproveRecordTask> results = new ArrayList<>();
        for (List<HistoryTaskResponse> g : groupStage) {
            String pass = String.valueOf(g.get(0).getVariables().get("pass"));
            //将待办合并
            if (pass.equals("todo")) {
                HistoryTaskResponse response = g.get(0);
                String users = g.stream()
                        .map(c -> c.getVariables().get("user"))
                        .filter(user -> user != null && !user.toString().isEmpty())
                        .map(Object::toString)
                        .collect(Collectors.joining(","));

                List<String> taskIds = g.stream().map(a -> a.getTaskId()).collect(Collectors.toList());
                List<String> userIds = g.stream().map(a -> a.getUserId()).collect(Collectors.toList());
                GTApproveRecordTask approveRecordTask = new GTApproveRecordTask();
                approveRecordTask.setTaskIds(taskIds);
                approveRecordTask.setTaskName(response.getTaskName());
                approveRecordTask.setCommitTime(response.getCommitTime());
                approveRecordTask.setUserIds(userIds);
                approveRecordTask.setProcessInstanceName(response.getProcessInstanceName());
                Map<String, Object> variables = new HashMap<>();
                variables.put("pass", "todo");
                variables.put("user", users);
                variables.put("remarks", "");
                approveRecordTask.setVariables(variables);
                approveRecordTask.setDescription(response.getDescription());
                approveRecordTask.setAssignees(Collections.singletonList(new GTApproveRecordTask.Assignee(users, response.getTaskId())));
                results.add(approveRecordTask);
            } else {
                for (HistoryTaskResponse response : g) {
                    GTApproveRecordTask approveRecordTask = new GTApproveRecordTask();
                    approveRecordTask.setTaskIds(Collections.singletonList(response.getTaskId()));
                    approveRecordTask.setTaskName(response.getTaskName());
                    approveRecordTask.setCommitTime(response.getCommitTime());
                    approveRecordTask.setUserIds(Collections.singletonList(response.getUserId()));
                    approveRecordTask.setProcessInstanceName(response.getProcessInstanceName());
                    approveRecordTask.setVariables(response.getVariables());
                    approveRecordTask.setDescription(response.getDescription());
                    Map<String, Object> variables = response.getVariables();
                    String user = response.getUserId();
                    if (!org.springframework.util.CollectionUtils.isEmpty(variables) && variables.get("user") != null) {
                        user = variables.get("user").toString();
                    }
                    approveRecordTask.setAssignees(Collections.singletonList(new GTApproveRecordTask.Assignee(user, response.getTaskId())));
                    results.add(approveRecordTask);
                }
            }
        }
        return results;
    }

    private void extracted(List<HistoryTaskResponse> historyTaskByCurrentProcessInstances) {
        List<String> userList = historyTaskByCurrentProcessInstances.stream().map(HistoryTaskResponse::getUserId).collect(Collectors.toList());
        HashSet<String> userIdSet = new HashSet<>(userList);
        String[] userIds = new String[userIdSet.size()];
        CSysUser cSysUser = new CSysUser();
        userIdSet.toArray(userIds);
        cSysUser.setLoginCodes(userIds);
        List<SysUser> sysUserByCdt = userApiSvc.getSysUserByCdt(cSysUser);
        Map<String, SysUser> sysUserMap = sysUserByCdt.parallelStream()
                .collect(Collectors.toMap(SysUser::getLoginCode, u -> u));
        for (HistoryTaskResponse historyTaskByCurrentProcessInstance : historyTaskByCurrentProcessInstances) {
            String userId = historyTaskByCurrentProcessInstance.getUserId();
            Map<String, Object> variables = historyTaskByCurrentProcessInstance.getVariables();
            variables.put("user", sysUserMap.containsKey(userId) ? sysUserMap.get(userId).getUserName() : userId);
            variables.put("icon", sysUserMap.containsKey(userId) ? sysUserMap.get(userId).getIcon() : "");
        }
        // 从第二个节点开始
        for (int i = 1; i < historyTaskByCurrentProcessInstances.size(); i++) {
            HistoryTaskResponse historyTaskResponse = historyTaskByCurrentProcessInstances.get(i);
            if (historyTaskResponse != null) {
                // 如果是通过操作
                if (historyTaskResponse.getVariables().get("pass").equals("pass")) {
                    // 查看上一个操作是不是撤回
                    HistoryTaskResponse historyTaskResponse1 = historyTaskByCurrentProcessInstances.get(i - 1);
                    if (historyTaskResponse1.getVariables().get("pass").equals("recall")) {
                        Map<String, Object> variables = historyTaskResponse.getVariables();
                        variables.put("pass", "submit");
                    }
                }
            }
        }
    }
}
